#include "main_app.h"
#include "esp_sntp.h"
#include "http_flie_server.h"
#include "time_sntp_driver.h"
#include "camera_driver.h"
#include "sd_fatfs_driver.h"
#include "szp_hardware_driver.h"
#include "my_ui_api.h"
#include "actions.h"
#include "ui.h"
#include "screens.h"
#include "vars.h"
#include "fonts.h"
#include "styles.h"

static const char *TAG = "app";
const char *file_photo_quality_config = MOUNT_POINT "/config/photo_quality_config";
const char *file_photo_pixel_config = MOUNT_POINT "/config/photo_pixel_config";

extern TaskHandle_t task_camera_get_handle, task_camera_show_handle, task_take_photo_handle;
extern bool camera_tasks_enabled, take_photo_enabled;
void action_menu_button_clicked(lv_event_t *e)
{
    vTaskSuspend(task_camera_get_handle);
    vTaskSuspend(task_camera_show_handle);
    vTaskSuspend(task_take_photo_handle);

    camera_tasks_enabled = false;
    take_photo_enabled = false;

    ESP_LOGI(TAG, "disable camera_tasks take_photo");
    eez_flow_set_screen(SCREEN_ID_PAGE_1, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
}

void action_back_button_clicked(lv_event_t *e)
{
    if (get_var_save__button_statue() == false)
    {
        eez_flow_set_screen(SCREEN_ID_SAVE_SETTING_WARN_MSEEAGE, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
        ESP_LOGI(TAG, "jump to warn page");
    }
    else
    {
        vTaskResume(task_camera_get_handle);
        vTaskResume(task_camera_show_handle);
        vTaskResume(task_take_photo_handle);

        camera_tasks_enabled = true;
        take_photo_enabled = true;
        eez_flow_set_screen(SCREEN_ID_HOME, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
        ESP_LOGI(TAG, "jump to home page");
    }
}

void action_tinyusb_switch_clicked(lv_event_t *e)
{
    if (get_var_use_tinyusb() == true)
    {
        ESP_LOGI(TAG, "TinyUSB is starting");
        tinyusb_start();

        lv_obj_t *obj = lv_msgbox_create(objects.page_1, "", "", 0, true);
        lv_obj_set_pos(obj, 70, 67);
        lv_obj_set_size(obj, 209, 121);
        {
            lv_obj_t *parent_obj = obj;
            {
                lv_obj_t *obj = lv_label_create(parent_obj);
                lv_obj_set_style_text_font(obj, &ui_font_cn, LV_PART_MAIN | LV_STATE_DEFAULT);
                lv_obj_set_pos(obj, -87, -227);
                lv_obj_set_size(obj, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
                lv_label_set_text(obj, "成功挂载虚拟U盘,请将相机通\n过Type-C线缆连接设备。");
                lv_obj_set_style_align(obj, LV_ALIGN_DEFAULT, LV_PART_MAIN | LV_STATE_DEFAULT);
            }
        }
    }
    else
    {
    }
}

void action_reboot_button_clicked(lv_event_t *e)
{
    char buf[10];
    ESP_ERROR_CHECK(sd_write_file(file_photo_quality_config, itoa(get_var_photo_quality(), buf, 10)));
    ESP_ERROR_CHECK(sd_write_file(file_photo_pixel_config, itoa(get_var_select_pixel(), buf, 10)));
    save_time_into_file();
    esp_system_abort("Manual reset triggered");
    esp_restart();
}

void task_wifi_connect(void *arg)
{
    char *ssid_str = lv_label_get_text(objects.wlan_name_label);
    const char *passwd_str = lv_textarea_get_text(objects.wifi_passwd_text);
    ESP_LOGI(TAG, "connect to ssid = %s, passwd = %s", ssid_str, passwd_str);
    // wifi_init(WIFI_MODE_STA, false);
    wifi_connect((uint8_t *)ssid_str, (uint8_t *)passwd_str);
    vTaskDelete(NULL);
}

void action_connect_wifi_button_clicked(lv_event_t *e)
{
    TaskHandle_t task_wifi_connect_handle;
    if (xTaskCreatePinnedToCore(task_wifi_connect, "task_wifi_connect", 4096, NULL, 4, &task_wifi_connect_handle, 0) == pdPASS)
    {
        ESP_LOGI(TAG, "task_wifi_connect create success");
        show_spinner();
    }
    else
    {
        ESP_LOGI(TAG, "task_wifi_connect create fail");
    }
}

void action_see_passwd_img_clicked(lv_event_t *e)
{
    extern lv_img_dsc_t img_can_see, img_can_not_see;
    if (lv_textarea_get_password_mode(objects.wifi_passwd_text))
    {
        lv_textarea_set_password_mode(objects.wifi_passwd_text, false);
        lv_img_set_src(objects.see_passwd_img, &img_can_see);
    }
    else
    {
        lv_textarea_set_password_mode(objects.wifi_passwd_text, true);
        lv_img_set_src(objects.see_passwd_img, &img_can_not_see);
    }
}

void action_wifi_passwd_insert(lv_event_t *e)
{

    const char *passwd_str = lv_textarea_get_text(objects.wifi_passwd_text);
    ESP_LOGI(TAG, "passwd = %s,size = %d", passwd_str, strlen(passwd_str));
    if (strlen(passwd_str) < 8)
    {
        lv_obj_add_state(objects.connect_wifi_button, LV_STATE_DISABLED);
    }
    else
    {
        lv_obj_clear_state(objects.connect_wifi_button, LV_STATE_DISABLED);
    }
}

void picture_select_cb(lv_event_t *e)
{
    const char *file_name = (const char *)lv_event_get_user_data(e);
    ESP_LOGI(TAG, "click = %s", file_name);
    // eez_flow_set_screen(SCREEN_ID_PICTURE_SHOW_NOW, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
    // char path[20];
    // lv_label_set_text(objects.fille_name_label, file_name);
    // sprintf(path, "S:/%s", file_name);
    // lv_img_set_src(objects.picture_show_img, path);
    show_picture(file_name);
}

void action_switch_to_picture_show_page(lv_event_t *e)
{
    lv_obj_clean(objects.picture_list);
    struct dirent *dir;
    DIR *dirp;
    int ret = 0;

    /* 打开目录 */
    dirp = opendir(MOUNT_POINT);
    if (NULL == dirp)
    {
        perror("opendir error");
        exit(-1);
    }

    /* 循环读取目录流中的所有目录条目 */
    errno = 0;
    while (NULL != (dir = readdir(dirp)))
    {
        char *dot = strrchr(dir->d_name, '.'); // 查找最后一个点号
        if (dot != NULL && (strcasecmp(dot, ".jpg") == 0))
        {
            ESP_LOGI(TAG, "Found JPG file: %s", dir->d_name);
            add_jpg_dir(dir->d_name);
        }
    }

    if (0 != errno)
    {
        perror("readdir error");
        ret = -1;
        goto err;
    }
    else
        printf("End of directory!\n");

err:
    closedir(dirp);
}

void wifi_select_cb(lv_event_t *e)
{
    const char *ssid = (const char *)lv_event_get_user_data(e);
    eez_flow_set_screen(SCREEN_ID_WIFI_CONNECT_PAGE_2, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
    ESP_LOGI(TAG, "select wifi ssid = %s", ssid);
    lv_label_set_text(objects.wlan_name_label, ssid);
}

static void time_sync_notification_cb(struct timeval *tv)
{
    close_spinner();
    eez_flow_set_screen(SCREEN_ID_SHOW_SNTP_TIME_PAGE, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
    save_time_into_file();
}

void task_sntp(void *arg)
{
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    esp_sntp_setservername(0, "ntp1.aliyun.com"); // 阿里云 NTP 服务器
    esp_sntp_setservername(1, "cn.pool.ntp.org"); // 中国 NTP 服务器
    esp_sntp_setservername(2, "pool.ntp.org");    // 默认服务器

    // 注册时间同步回调函数
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);

    esp_sntp_init();
    setenv("TZ", "CST-8", 1);
    tzset();
    vTaskDelete(NULL);
}

void wifi_connect_cb()
{
    TaskHandle_t task_sntp_handle;
    xTaskCreatePinnedToCore(task_sntp, "task_sntp", 4096, NULL, 4, &task_sntp_handle, 1);
}

void task_wifi(void *arg)
{
    uint16_t number = 10;
    uint16_t ap_count = 0;
    static wifi_ap_record_t ap_info[10] DRAM_ATTR;

    wifi_init(WIFI_MODE_STA, false);
    vTaskDelay(10);

    UBaseType_t watermark = uxTaskGetStackHighWaterMark(NULL);
    ESP_LOGI(TAG, "1WiFi Task Stack Free: %d", watermark);

    esp_wifi_scan_start(NULL, true);
    ESP_LOGI(TAG, "Max AP number ap_info can hold = %u", number);

    watermark = uxTaskGetStackHighWaterMark(NULL);
    ESP_LOGI(TAG, "2WiFi Task Stack Free: %d", watermark);

    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_count));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
    ESP_LOGI(TAG, "Total APs scanned = %u, actual AP number ap_info holds = %u", ap_count, number);
    vTaskDelay(10);

    watermark = uxTaskGetStackHighWaterMark(NULL);
    ESP_LOGI(TAG, "3WiFi Task Stack Free: %d", watermark);

    for (int i = 0; i < number; i++)
    {
        lvgl_port_lock(0);
        add_wifi_panel(ap_info[i].rssi, (char *)ap_info[i].ssid, ap_info[i].authmode != WIFI_AUTH_OPEN);
        lvgl_port_unlock();
        vTaskDelay(pdMS_TO_TICKS(10));
    }

    watermark = uxTaskGetStackHighWaterMark(NULL);
    ESP_LOGI(TAG, "4WiFi Task Stack Free: %d", watermark);

    eez_flow_set_screen(SCREEN_ID_WIFI_CONNECT_PAGE, LV_SCR_LOAD_ANIM_FADE_ON, 200, 0);
    lv_obj_add_flag(objects.spinner_1, LV_OBJ_FLAG_HIDDEN);
    vTaskDelete(NULL);
}

void action_button_sntp_clicked(lv_event_t *e)
{
    lv_obj_clear_flag(objects.spinner_1, LV_OBJ_FLAG_HIDDEN);
    ESP_LOGI(TAG, "action_button_sntp_clicked");
    TaskHandle_t task_wifi_handle;
    xTaskCreatePinnedToCore(task_wifi, "task_wifi", 4096 * 5, NULL, 4, &task_wifi_handle, 1);
}

void task_time_frush(void *arg)
{
    char time_str[32];
    // char *task_list_buffer = malloc(1024);;
    while (1)
    {
        get_time_from_sys(time_str);
        set_var_now_time_str(time_str);
        vTaskDelay(pdMS_TO_TICKS(1000));

        // vTaskList(task_list_buffer);
        // printf("======== Task States ========\n");
        // printf("%s", task_list_buffer);
        // printf("\nFreeHeapSize:%d\n", xPortGetFreeHeapSize());
    }
}

void main_task_start(void)
{
    char buf[10];
    struct stat st;

    ESP_LOGI(TAG, "get_var_select_pixel() = %d", get_var_select_pixel());
    ESP_LOGI(TAG, "get_var_photo_quality() = %d", get_var_photo_quality());
    sd_fatfs_init();
    set_time_from_file();

    if (stat(MOUNT_POINT "/config", &st) == 0 && S_ISDIR(st.st_mode))
    {
        ESP_LOGI(TAG, "config dir already exist");
    }
    else
    {
        ESP_LOGI(TAG, "config dir not exist, create it");
        mkdir(MOUNT_POINT "/config", 0777);
    }

    if (sd_read_file(file_photo_quality_config, buf) != ESP_OK)
    {
        ESP_ERROR_CHECK(sd_write_file(file_photo_quality_config, itoa(get_var_photo_quality(), buf, 10)));
    }
    int photo_quality = (int)(63 - (float)atoi(buf) / 100 * 63);
    set_var_photo_quality(atoi(buf));

    if (sd_read_file(file_photo_pixel_config, buf) != ESP_OK)
    {
        ESP_ERROR_CHECK(sd_write_file(file_photo_pixel_config, itoa(get_var_select_pixel(), buf, 10)));
    }
    framesize_t photo_pixel;
    set_var_select_pixel(atoi(buf));

    switch (atoi(buf))
    {
    case 0:
        photo_pixel = FRAMESIZE_QVGA;
        break;

    case 1:
        photo_pixel = FRAMESIZE_QQVGA;
        break;

    case 2:
        photo_pixel = FRAMESIZE_VGA;
        break;

    default:
        photo_pixel = FRAMESIZE_QVGA;
        break;
    }
    ESP_LOGI(TAG, "success get photo config, quality=%d,pixel=%d", photo_quality, photo_pixel);

    camera_init(photo_quality, photo_pixel);
    buttton_init();

    xTaskCreatePinnedToCore(task_take_photo, "task_take_photo", 5 * 1024, NULL, 5, &task_take_photo_handle, 1);
    xTaskCreatePinnedToCore(task_camera_get, "task_camera_get", 5 * 1024, NULL, 5, &task_camera_get_handle, 1);
    xTaskCreatePinnedToCore(task_camera_show, "task_camera_show", 5 * 1024, NULL, 5, &task_camera_show_handle, 0);
    xTaskCreatePinnedToCore(task_time_frush, "task_time_frush", 5 * 1024, NULL, 5, NULL, 0);
}
